﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;

namespace GPMS.Extension
{
    public class Validation
    {
        public static void ValidationAttributes<TEntity>(TEntity entity)
        {
            var validationInstance = new Validation();
            validationInstance.ValidateAttributesInternal(entity);
        }

        private  void ValidateAttributesInternal<TEntity>(TEntity entity)
        {
            var validationIssues = new List<ValidationIssue>();
            var entityType=typeof(TEntity);
            var props = entityType.GetProperties();
            var metatype = entityType.GetCustomAttributes(typeof(MetadataTypeAttribute), false).FirstOrDefault();
            var type = ((MetadataTypeAttribute)metatype).MetadataClassType;
            var s = type.GetProperties();
            var customAttrs = entityType.GetCustomAttributes(true).Where(t => t.GetType().Namespace.Contains("ValidationMeta"));
            foreach (var attr in customAttrs)
            {
                var validate = (ValidationAttribute)attr;
                //执行 附加在 linqtosql partial 类 上的 ValidationAttribute 验证方法
                bool valid = validate.IsValid(entity);
                if (!valid)
                {
                    validationIssues.Add(new ValidationIssue(null, null, validate.ErrorMessage));
                }
                //执行附加在  linqtosql partial 类 属性上的 ValidationAttribute 验证方法
                foreach (var prop in s)
                {
                    ValidateProperty(validationIssues, entity, prop);
                }
                // throw exception?
                if (validationIssues.Count > 0)
                {
                    throw new ValidationIssueException(validationIssues);
                }
            }
        }

        private void ValidateProperty<TEntity>(List<ValidationIssue> validationIssues, TEntity entity, System.Reflection.PropertyInfo property)
        {
            //得到验证特性的集合
            var validators = property.GetCustomAttributes(typeof(ValidationAttribute), false);
            foreach (ValidationAttribute validator in validators)
            {
                ValidateValidator(validationIssues, entity, property, validator);
            }
        }

        private void ValidateValidator<TEntity>(List<ValidationIssue> validationIssues, TEntity entity, System.Reflection.PropertyInfo property, ValidationAttribute validator)
        {
            var dataEntityProperty = typeof(TEntity).GetProperties().FirstOrDefault(p => p.Name == property.Name);
            var value = dataEntityProperty.GetValue(entity, null);
            if (!validator.IsValid(value))
            {
                validationIssues.Add(new ValidationIssue(property.Name, value, validator.ErrorMessage));
            }
        }
    }
}
